home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug191 / play.c < prev    next >
Text File  |  1986-05-25  |  9KB  |  299 lines

  1.  
  2. /*  PLAY.C                              Last update: 20 Feb 86  */
  3.  
  4. /* ------------------------------------------------------------ */
  5. /*      This is a portion of the SOUND EFFECTS LIBRARY.         */
  6. /*                                                              */
  7. /*      Copyright (C) 1986 by Paul Canniff.                     */
  8. /*      All rights reserved.                                    */
  9. /*                                                              */
  10. /*      This library has been placed into the public domain     */
  11. /*      by the author.  Use is granted for non-commercial       */
  12. /*      pusposes, or as an IMBEDDED PORTION of a commercial     */
  13. /*      product.                                                */
  14. /*                                                              */
  15. /*      Paul Canniff                                            */
  16. /*      PO Box 1056                                             */
  17. /*      Marlton, NJ 08053                                       */
  18. /*                                                              */
  19. /*      CompuServe ID: 73047,3715                               */
  20. /*                                                              */
  21. /* ------------------------------------------------------------ */
  22.  
  23.  
  24. #define DEBUG 0
  25.  
  26. #include <stdio.h>
  27. #include "sound.h"
  28.  
  29.  
  30.     /* The following table lists the frequencies of the 84 notes */
  31.     /* in terms of Hz * 100.  It is taken from the ??? scale.    */
  32.  
  33.  
  34. static long std_note_freq[] = {  
  35.    /* Pause */             0, 
  36.    /* Octave 0 */       1635,   1732,   1835,   1945,   2060,   2183,  
  37.                         2312,   2450,   2596,   2750,   2914,   3087,
  38.    /* Octave 1 */       3270,   3465,   3671,   3889,   4120,   4365,
  39.                         4625,   4900,   5191,   5500,   5827,   6174,
  40.    /* Octave 2 */       6541,   6930,   7342,   7778,   8241,   8731,
  41.                         9250,   9800,  10383,  11000,  11654,  12347,
  42.    /* Octave 3 */      13081,  13859,  14683,  15556,  16481,  17461,
  43.                        18500,  19600,  20765,  22000,  23308,  24694,
  44.    /* Octave 4 */      26163,  27718,  29366,  31113,  32963,  34923,
  45.                        36999,  39200,  41530,  44000,  46616,  49388,
  46.    /* Octave 5 */      52325,  55437,  58733,  62225,  65926,  69846, 
  47.                        73999,  78399,  83061,  88000,  93233,  98777,
  48.    /* Octave 6 */     104650, 110873, 117466, 124451, 132851, 139691, 
  49.                       147998, 156798, 166122, 176000, 186466, 197553,
  50.    /* Octave 7 */     209300, 221746, 234932, 248902, 263702, 279383,
  51.                       295996, 313596, 332244, 352000, 372931, 395107, 
  52.    /* Octave 8 */     418601  };
  53.  
  54.  
  55. #define MAX_OCTAVE 7
  56. #define LEGATO 0
  57. #define NORMAL 1
  58. #define STACCATO 2
  59. #define NPO 12          /* Notes per octave */
  60. #define FLAT -1
  61. #define SHARP 1
  62.  
  63. static int note_length=1, note_mode=NORMAL, tempo=DEF_TEMPO;
  64.  
  65. int play(mstr)
  66. char *mstr;
  67. {
  68.     int dots, fs, error, note, time, i;
  69.     static int octave=DEF_OCTAVE;
  70.     char c;
  71.  
  72.     error = 0;
  73.  
  74.     while (!error)
  75.     {
  76.         switch (c = toupper(*mstr++))
  77.         {
  78.             case '\0':  return 0;   /* End of string */
  79.  
  80.             case ' ':
  81.             case ';':
  82.             case ',':   break;      /* Ignore - used for decoration */
  83.  
  84.             case 'A':
  85.             case 'B':   
  86.             case 'C':   
  87.             case 'D':   
  88.             case 'E':   
  89.             case 'F':   
  90.             case 'G':   fs = flatsharp(&mstr);
  91.                         note = noteval(c) + fs + (NPO * octave) + 1;
  92.                         if (note == 0) note = 1;  /* Trap for low C-flat */
  93.                         time = compute_time(&mstr);
  94.                         dots = num_dots(&mstr);
  95.                         do_note(note,time,dots);
  96.                         break;
  97.  
  98.             case 'L':   if ((i = extrint(&mstr)) < 0)
  99.                             error = 1;
  100.                         else
  101.                         {
  102.                             if (i < 1 || i > 64) error = 1;
  103.                             note_length = i;
  104. #if DEBUG
  105.                             printf("Note Len set to %d\n",i);
  106. #endif
  107.                         }
  108.                         break;
  109.  
  110.             case 'M':   switch (toupper(*mstr++))
  111.                         {
  112.                             case 'N':   note_mode = NORMAL;
  113.                                         printf("Mode NORMAL\n");
  114.                                         break;
  115.  
  116.                             case 'L':   note_mode = LEGATO;
  117.                                         printf("Mode LEGATO\n");
  118.                                         break;
  119.  
  120.                             case 'S':   note_mode = STACCATO;
  121.                                         printf("Mode STACCATO\n");
  122.                                         break;
  123.  
  124.                             default:    error = 1;
  125.                                         break;
  126.                         }
  127.                         break;
  128.  
  129.             case 'N':   if ((note = extrint(&mstr)) < 0)
  130.                             error = 1;
  131.                         else
  132.                         {
  133.                             if ((time = extrint(&mstr)) < 0)
  134.                                 time = note_length;
  135.                             if (do_note(note,time,0) != 0)
  136.                                 error = 1;
  137.                         }
  138.                         break;
  139.  
  140.             case 'O':   octave = extrint(&mstr);
  141.                         if (octave < 0 || octave > 6)
  142.                             error = 1;
  143. #if DEBUG
  144.                         else
  145.                             printf("Octave set to %d\n",octave);
  146. #endif
  147.                         break;
  148.  
  149.             case '<':   if (octave > 0) octave--;
  150.                         break;
  151.  
  152.             case '>':   if (octave < MAX_OCTAVE) octave++;
  153.                         break;
  154.  
  155.             case 'P':   if ((time = extrint(&mstr)) < 0)
  156.                             error = 1;
  157.                         else
  158.                         {
  159. #if DEBUG
  160.                             printf("Pausing 1/%d %d dots\n",time,dots);
  161. #endif
  162.                             dots = num_dots(&mstr);
  163.                             do_note(0,time,dots);
  164.                         }
  165.                         break;
  166.  
  167.             case 'T':   tempo = extrint(&mstr);
  168.                         if (tempo < 4) tempo = 4;
  169.                         if (tempo > 256) tempo = 256;
  170. #if DEBUG
  171.                         printf("Tempo is %d\n",tempo);
  172. #endif
  173.                         break;
  174.  
  175.             default:    error = 1;
  176.                         break;
  177.  
  178.         }
  179.     }
  180.  
  181.     return (error ? -1 : 0);
  182. }
  183.  
  184.  
  185. static int do_note(n,t,d)
  186. int n,t,d;
  187. {
  188.     long freq;
  189.     unsigned tot_time, pause_time, note_time, dot_high, dot_low;
  190.  
  191.     if (n < 0 || n > 84) return -1;
  192.  
  193. #if DEBUG
  194.     printf("    Doing note %d t %d dots %d\n",n,t,d);
  195. #endif
  196.  
  197.     dot_high = dot_low = 1;
  198.     while (d--)
  199.     {
  200.         dot_high *= 3;
  201.         dot_low *= 2;
  202.     }
  203.  
  204.     freq = std_note_freq[n];
  205.     tot_time = ((4000 * dot_high) / (t * tempo * dot_low));
  206.     pause_time = (tot_time / 8) * note_mode;
  207.     note_time = tot_time - pause_time;
  208.  
  209. #if DEBUG
  210.     printf("    Freq %ld time T %d P %d N %d\n",freq,tot_time,
  211.                           pause_time,note_time);
  212. #endif
  213.  
  214.     sound(freq,note_time);
  215.     sound(0L,pause_time);
  216.  
  217.     return 0;
  218. }
  219.  
  220.     /*  EXTRINT -- extracts integer, advances pointer */
  221.  
  222. static int extrint(sp)
  223. char **sp;
  224. {
  225.     register int digits = 0, val = 0;
  226.  
  227.     while (digits < 3 && isdigit(**sp))
  228.     {
  229.         val = (val * 10) + (**sp - '0');
  230.         (*sp)++;
  231.         digits++;
  232.     }
  233.  
  234.     if (digits == 0) return -1;
  235.       else           return val;
  236. }
  237.  
  238.  
  239. static int noteval(c)
  240. char c;
  241. {
  242.     static int note_lookup[] = { 9,11,0,2,4,5,7 };
  243.  
  244.     if (c < 'A' || c > 'G') return 0;
  245.       else                  return note_lookup[c-'A'];
  246. }
  247.  
  248. static int flatsharp(sp)
  249. char **sp;
  250. {
  251.     if (**sp == '+' || **sp == '#')
  252.     {
  253. #if DEBUG
  254.         printf("  Note is sharp\n");
  255. #endif
  256.         (*sp)++;
  257.         return SHARP;
  258.     }
  259.     else if (**sp == '-')
  260.     {
  261. #if DEBUG
  262.         printf("  Note is flat\n");
  263. #endif
  264.         (*sp)++;
  265.         return FLAT;
  266.     }
  267.     else
  268.     {
  269.         return 0;
  270.     }
  271. }
  272.  
  273.  
  274. static int compute_time(sp)
  275. char **sp;
  276. {
  277.     int l;
  278.  
  279.     if ((l = extrint(sp)) < 0)  return note_length;
  280.       else                      return l;
  281. }
  282.  
  283.  
  284. static int num_dots(sp)
  285. char **sp;
  286. {
  287.     int count;
  288.  
  289.     count = 0;
  290.     while (**sp == '.')
  291.     {
  292.         (*sp)++;
  293.         count++;
  294.     }
  295.     return count;
  296. }
  297.  
  298.  
  299.